package com.ruoyi.common.utils.jm.ofd;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
import java.util.UUID;

import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x509.TBSCertificate;
import org.bouncycastle.asn1.x509.Time;
import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
import org.bouncycastle.cert.bc.BcX509ExtensionUtils;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64Encoder;


public class SM2CryptoForAgreement {

	public static byte[] SignData(byte[] bPlain,byte[] bPfx,String sPin) throws IOException {
		// TODO Auto-generated method stub
		String algorithm = "SM3withSM2";
		String password = sPin;
		Security.addProvider(new BouncyCastleProvider());

		KeyStore ks2;
		try {
			ks2 = KeyStore.getInstance("PKCS12", "BC");
			ByteArrayInputStream bys = new ByteArrayInputStream(bPfx);
			ks2.load(bys, password.toCharArray());
			Enumeration<String> enum1 = ks2.aliases();
			String keyAlias = null;
	        if (enum1.hasMoreElements())
	        {
	            keyAlias = (String)enum1.nextElement();
	        }
	        Signature sig = Signature.getInstance(algorithm, "BC");

	        sig.initSign((PrivateKey) ks2.getKey(keyAlias, null), new SecureRandom());
	        sig.update(bPlain);
	        byte[] rs = sig.sign();
			bys.close();
	        return rs;
		} catch (KeyStoreException | NoSuchProviderException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {
			e.printStackTrace();
		} catch (SignatureException e) {
			e.printStackTrace();
		}
		return null;
	}


    private static byte[] GetPublicKey(byte[] bCert)
    {
        try{
        	Security.addProvider(new BouncyCastleProvider());
            X509Certificate x509Certificate = null;
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
            ByteArrayInputStream bInput = new ByteArrayInputStream(bCert);
            x509Certificate = (X509Certificate) certificateFactory.generateCertificate(bInput);
            PublicKey publicKey = x509Certificate.getPublicKey();
            byte[] bRet = new byte[64];
            byte[] bPub = publicKey.getEncoded();
            System.arraycopy(bPub, bPub.length - 64, bRet, 0, 64);
            return bRet;
        }
        catch(Exception ex)
        {
            System.out.println(ex);
            return null;
        }
    }

    public static byte[] GetHashForSign(byte[] bCert,byte[] bSealForSign){
       	byte[] bPublicKey = GetPublicKey(bCert);
    	byte[] input = new byte[210];
    	String s1 = "00,80,31,32,33,34,35,36,37,38,31,32,33,34,35,36,37,38,FF,FF,FF,FE,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FC,28,E9,FA,9E,9D,9F,5E,34,4D,5A,9E,4B,CF,65,09,A7,F3,97,89,F5,15,AB,8F,92,DD,BC,BD,41,4D,94,0E,93,32,C4,AE,2C,1F,19,81,19,5F,99,04,46,6A,39,C9,94,8F,E3,0B,BF,F2,66,0B,E1,71,5A,45,89,33,4C,74,C7,BC,37,36,A2,F4,F6,77,9C,59,BD,CE,E3,6B,69,21,53,D0,A9,87,7C,C6,2A,47,40,02,DF,32,E5,21,39,F0,A0,4e,70,ed,ea,ad,ec,e1,3e,b9,5b,59,53,46,f5,13,34,e0,e4,af,3e,54,f8,2b,09,5f,b5,64,9c,73,c6,7a,29,2b,4a,75,18,1e,4a,ce,79,5a,ee,6a,9a,d3,c3,39,98,c5,62,6d,0a,06,16,9b,16,12,82,f1,18,4c,af,45,89";
    	String[] s = s1.split(",");
    	for(int i=0;i<210;i++)
    	{
    		input[i] = (byte)Integer.parseInt(s[i], 16);
    	}
    	System.arraycopy(bPublicKey, 0, input, 210-64, 32);
    	System.arraycopy(bPublicKey, 32, input, 210-32, 32);
    	byte[] bHash = GmUtil.sm3(input);
    	int iLen = bHash.length + bSealForSign.length;
    	byte[] bPlain = new byte[iLen];
    	System.arraycopy(bHash, 0, bPlain, 0, bHash.length);
    	System.arraycopy(bSealForSign, 0, bPlain, bHash.length, bSealForSign.length);
    	bHash = GmUtil.sm3(bPlain);
    	return bHash;
    }

    public static byte[] SignDateForSeal(byte[] bMakerCert,byte[] bSealForSign,String sPublicKey,String sPrivateKey) throws IOException
    {
    	byte[] bPublicKey = GetPublicKey(bMakerCert);
    	byte[] input = new byte[210];
    	String s1 = "00,80,31,32,33,34,35,36,37,38,31,32,33,34,35,36,37,38,FF,FF,FF,FE,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,FF,00,00,00,00,FF,FF,FF,FF,FF,FF,FF,FC,28,E9,FA,9E,9D,9F,5E,34,4D,5A,9E,4B,CF,65,09,A7,F3,97,89,F5,15,AB,8F,92,DD,BC,BD,41,4D,94,0E,93,32,C4,AE,2C,1F,19,81,19,5F,99,04,46,6A,39,C9,94,8F,E3,0B,BF,F2,66,0B,E1,71,5A,45,89,33,4C,74,C7,BC,37,36,A2,F4,F6,77,9C,59,BD,CE,E3,6B,69,21,53,D0,A9,87,7C,C6,2A,47,40,02,DF,32,E5,21,39,F0,A0,4e,70,ed,ea,ad,ec,e1,3e,b9,5b,59,53,46,f5,13,34,e0,e4,af,3e,54,f8,2b,09,5f,b5,64,9c,73,c6,7a,29,2b,4a,75,18,1e,4a,ce,79,5a,ee,6a,9a,d3,c3,39,98,c5,62,6d,0a,06,16,9b,16,12,82,f1,18,4c,af,45,89";
    	String[] s = s1.split(",");
    	for(int i=0;i<210;i++)
    	{
    		input[i] = (byte)Integer.parseInt(s[i], 16);
    	}
    	System.arraycopy(bPublicKey, 0, input, 210-64, 32);
    	System.arraycopy(bPublicKey, 32, input, 210-32, 32);
    	byte[] bHash = GmUtil.sm3(input);
    	int iLen = bHash.length + bSealForSign.length;
    	byte[] bPlain = new byte[iLen];
    	System.arraycopy(bHash, 0, bPlain, 0, bHash.length);
    	System.arraycopy(bSealForSign, 0, bPlain, bHash.length, bSealForSign.length);
    	bHash = GmUtil.sm3(bPlain);

    	AsymmetricCipherKeyPair bcPair = SM2UtilForAgreement.ConvertToBCKeyPair(sPublicKey, sPrivateKey);

    	if(bcPair == null) {
    		return null;
    	}
    	byte[] bVal = GmUtil.sm2(bHash, bcPair);
    	return bVal;
    }
}


